from system.fsm import Fsm
from system.eventServer import eventServer
from system.timer import Timer
from system.vec2 import Vec2

import math
import random

class Weapon(Fsm):
    def __init__(self, parent, type = None, name = None):
        Fsm.__init__(self, parent, ['update'], type, name)
        
        self.unit = self.searchAncestors("type","shudai.unit")
        self.bullets = self.searchAncestors("type","shudai.shudai").search("name","bullets",False)
        
        self.defaultVar("renderOp2d","sceneNode")
        self.defaultVar("turnSpeed",3)
        self.defaultVar("range",300)
        self.defaultVar("fireTime",0.1)
        self.defaultVar("gfx","")
        self.defaultVar("rot",0)
        self.defaultVar("pos",(0,0))
        self.defaultVar("scale",(1,1))
        self.defaultVar("bulletDeflection",0.2)
        self.defaultVar("bullet","")
        
        self.defaultVar("turnThreshold",0.1)
        
    def init(self):
        self.gfx = self.addChild(self.getVar("gfx"),"gfx")
        self.gfx.setVar("static",True)
        if self.gfx.getVar("hardpoints"):
            x,y = self.gfx.getVar("hardpoints")[0]
            self.gfx.setVar("pos",(-x,-y))
        
    def target(self, target):
        self.setVar("target",target)
        self.transition("target")
        
    def attack(self, target):
        self.setVar("target",target)
        self.transition("attack")
    
    def start_reset(self,cmd,args):
        self.updateReset = Timer(0.25)

    def update_reset(self,cmd,args):
        doneReset = False
        dtime = abs(args['dtime'])
        max_rot = self.getVar("turnSpeed") * dtime
        rot = self.getVar("rot")
        diffRot = rot
        while diffRot < -math.pi:
            diffRot += math.pi * 2
        while diffRot > math.pi:
            diffRot -= math.pi * 2
        if abs(diffRot) < max_rot:
            self.setVar("rot",0.0)
            self.transition("idle")
        else:
            if diffRot > 0.0:
                self.setVar("rot",diffRot - max_rot)
            else:
                self.setVar("rot",diffRot + max_rot)
        return False
    
    def start_target(self, cmd, args):
        self.updateTarget = Timer(0.25)
        self.target = self.getObject(self.getVar("target"))
        
    def end_target(self, cmd, args):
        self.target = None
        
    def update_target(self, cmd, args):
        onTarget = False
        
        if self.updateTarget.fire():
            self.updateTarget.reset()
            self.target = self.getObject(self.getVar("target"))
        
        if not self.target or self.target.getVar("dead"):
            self.transition("reset")
        else:
            
            dtime = args['dtime']
            pos = Vec2(self.unit.getVar("pos")) + Vec2(self.unit.getVar("scale")) * Vec2(self.getVar("pos"))
            rot = self.unit.getVar("rot") + self.getVar("rot") + math.pi/2
            
            targetPos = Vec2(self.target.getVar("pos"))
            diff = targetPos - pos
            diffLength = diff.length()
            if diffLength < self.unit.getVar("sight"):
                destRot = diff.angle()
                #diffRot = destRot - rot
                diffRot = rot - destRot + math.pi
                while diffRot < -math.pi:
                    diffRot += math.pi * 2
                while diffRot > math.pi:
                    diffRot -= math.pi * 2
                    
                turnThreshold = self.getVar("turnThreshold")
                
                if diffRot > turnThreshold:
                    self.setVar("rot",self.getVar("rot") - self.getVar("turnSpeed") * dtime)
                elif diffRot < -turnThreshold:
                    self.setVar("rot",self.getVar("rot") + self.getVar("turnSpeed") * dtime)
                elif diffLength < self.getVar("range"):
                    onTarget = True
                    
        return onTarget

    def start_attack(self, cmd, args):
        self.start_target(cmd,args)
        self.shotTimer = Timer(self.getVar("fireTime"))
        
    def update_attack(self, cmd, args):
        if self.update_target(cmd,args) and self.shotTimer.fire():
            self.shotTimer.reset()
            
            unitRot = self.unit.getVar("rot")
            unitPos = Vec2(self.unit.getVar("pos"))
            unitScale = Vec2(self.unit.getVar("scale"))
            
            myRot = self.getVar("rot") + unitRot
            bulletPos = myPos = unitPos + (unitScale * Vec2(self.getVar("pos"))).rotate(unitRot)
            
            deflect = self.getVar("bulletDeflection")
            bulletRot = myRot + math.pi/2 + random.uniform(-deflect,deflect)
            
            #myScale = Vec2(self.getVar("scale"))
            #hardpoint = Vec2(self.gfx.getVar("hardpoints")[1]) - Vec2(0.5,0.5)
            #bulletPos = myPos + (myScale * unitScale * hardpoint).rotate(myRot)
            
            bullet = self.bullets.addChild("shudai.bullet")
            bullet.load(self.getVar("bullet"))
            bullet.setVar("pos",bulletPos.toTuple())
            bullet.setVar("rot",bulletRot)
            bullet.setVar("target",self.getVar("target"))
            bullet.init()
